﻿using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Storage;
using Storage.EntityModels;
using System.Data.Linq;
using Stats.Objects;
using System.Xml;

namespace Stats
{  
    /// <summary>
    /// This class contains the statistics methods useful to other TripLOA modules.
    /// </summary>
    public static class StatsModule 
    {
        /// <summary>
        /// This object contains the configuration variables.
        /// </summary>
        public static ConfigurationData configData;

        /// <summary>
        /// This method initializes the stats configuration variables reading their values from the XML configuraion file.
        /// </summary>
        /// <param name="dataFile">The path of the XML configuration file</param>
        public static void Init(string dataFile)
        {
            configData = new ConfigurationData(dataFile);

            
            FuelCostPerLiterReference = configData.FuelCostPerLiterReference;

            EmissionMeasureDivisionUnit = configData.EmissionMeasureUnitDivision;

            PendingFeedback_ExpireDays = configData.PendingFeedback_ExpireDays;

            displayPendingFeedbackAfterDays = configData.PendingFeedback_DisplayAfterDays;

            MaxNumberOfUserTripsWithPendingFeedbacksToReturn = configData.MaxNumberOfUserTripsWithPendingFeedbacksToReturn;


            #region vehicles emissions references
            
            UtilitaryCarsEmissionsReference = configData.UtilitaryCarsEmissionsReference;
            SUVCarsEmissionsReference = configData.SUVCarsEmissionsReference;
            SportCarsEmissionsReference = configData.SportCarsEmissionsReference;
            SedanCarsEmissionsReference = configData.SedanCarsEmissionsReference;
            MPVCarsEmissionsReference = configData.MPVCarsEmissionsReference;
            MotorbikeEmissionsReference = configData.MotorbikeEmissionsReference;
            
            #endregion

            #region vehicles fuel consumption references
            
            UtilitaryCarsFuelConsumptionReference = configData.UtilitaryCarsFuelConsumptionReference;
            SUVCarsFuelConsumptionReference = configData.SUVCarsFuelConsumptionReference;
            SportCarsFuelConsumptionReference = configData.SportCarsFuelConsumptionReference;
            SedanCarsFuelConsumptionReference = configData.SedanCarsFuelConsumptionReference;
            MPVCarsFuelConsumptionReference = configData.MPVCarsFuelConsumptionReference;
            MotorbikeFuelConsumptionReference = configData.MotorbikeFuelConsumptionReference;
            
            #endregion



        }

        // WAIT TO DELETE
        ///// <summary>
        ///// This method is called when a trip is cancelled and removes the pending feedbacks associated with this trip from owner to passenger,
        ///// but not from passenger to owner, so they can insult him.
        ///// </summary>

        ///// <param name="tripID">The cancelled trip ID </param> 
        ///// <returns>A boolean that indicates the operation status</returns>
        //public static bool deletePendingFeedbacksOnCancellingTrip(int tripID)
        //{
        //    return AuxMethods.deletePendingFeedbacksOnCancellingTripOperation(tripID);
        //}

        //TO DELETE
        ///// <summary>
        ///// This method is called when a user wants to unsubscribe himself from a trip and removes the associated pending feedbacks
        ///// from passenger to owner, but not from owner to passenger, so he can insult him.
        ///// </summary>
        ///// <param name="tripID">The ID of the trip wich the user wants to unsubscribe</param>
        ///// <param name="userID">The ID of the user who is unsubscribed from the trip</param>
        ///// <returns>A boolean that indicates the operation status</returns>
        //public static bool deletePendingFeedbacksOnPassengerCancellationFromTrip(int tripID, int userID)
        //{
        //    return AuxUserMethods.deletePendingFeedbacksOnPassengerCancellationFromTripOperation(tripID, userID);
        //}
        // VALORI IN CASO UTENTE CHE HA LASCIATO UN FEEDBACK NON SIA PIU' REGISTRATO
        //public static int UnregisteredUserID = 0;
        //public static string UnregisteredUsername = "Unregistered User";
        //public static string noCommentLeftString = "No comment left";
        //public static bool insertNegativeFeedbackForOwner(int ownerID, int tripID, int senderID)
        //{
        //    return UpdateFeedbackModule.insertNegativeFeedbackForOwnerOperation(ownerID, tripID, senderID);
        //}

        //public static bool insertNegativeFeedbackForPassenger(int psnID, int tripID, int senderID)
        //{
        //    return UpdateFeedbackModule.insertNegativeFeedbackForPassengerOperation(psnID, tripID, senderID);
        //}

        // DEPRECATED 
        //public static List<FeedbackRequest> getPendingFeedbacks(int loggedUserID)
        //{
        //    return AuxUserMethods.getPendingFeedbacksToLeftOperation(loggedUserID);
        //}

        #region CONFIGURATION VARIABLES

        /// <summary>
        /// This enumeration contains the generic vehicle types that can be set by the user.
        /// </summary>
        public enum vehicleTypes
        {
            /// <summary>
            /// Utilitary vehicle type
            /// </summary>
            UtilitaryCarVehicleType = 0,

            /// <summary>
            /// Sedan vehicle type
            /// </summary>
            SedanCarVehicleType = 1,

            /// <summary>
            /// Sport vehicle type
            /// </summary>
            SportCarVehicleType = 2,

            /// <summary>
            /// SUV vehicle type
            /// </summary>
            SUVCarVehicleType = 3,

            /// <summary>
            /// Multi Purpose vehicle type
            /// </summary>
            MPVCarVehicleType = 4,

            /// <summary>
            /// Motorbike vehicle type
            /// </summary>
            MotorbikeVehicleType = 5,

            /// <summary>
            /// User hasn't an own vehicle
            /// </summary>
            NoOwnVehicle = 6,

            /// <summary>
            /// Error Vehicle Type
            /// </summary>
            UnknownVehicleType = -2
        };

        /// <summary>
        /// The fuel cost per liter used in TripLOA.
        /// </summary>
        public static double FuelCostPerLiterReference;

        /// <summary>
        /// Specifies the emission measure division unit...now emissions are returned in quintals of Co2
        /// </summary>
        public static int EmissionMeasureDivisionUnit;

        /// <summary>
        /// This variable contains the emissions reference values for the vehicle types: Utilitary cars
        /// </summary>
        public static int UtilitaryCarsEmissionsReference;
        
        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: Sedan cars
        /// </summary>
        public static int SedanCarsEmissionsReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: Sport cars
        /// </summary>
        public static int SportCarsEmissionsReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: SUV cars
        /// </summary>
        public static int SUVCarsEmissionsReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: MPV cars
        /// </summary>
        public static int MPVCarsEmissionsReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: Motorbike
        /// </summary>
        public static int MotorbikeEmissionsReference;
        

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: Utilitary cars
        /// </summary>
        public static float UtilitaryCarsFuelConsumptionReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: Sedan cars
        /// </summary>
        public static float SedanCarsFuelConsumptionReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: Sport cars
        /// </summary>
        public static float SportCarsFuelConsumptionReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: SUV cars
        /// </summary>
        public static float SUVCarsFuelConsumptionReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: MPV cars
        /// </summary>
        public static float MPVCarsFuelConsumptionReference;

        /// <summary>
        /// This variable contains the fuel consumption reference values for the vehicle types: Motorbikes
        /// </summary>
        public static float MotorbikeFuelConsumptionReference;


       

        /// <summary>
        /// These days after the trip departure date, a pending feedback expires and is removed from PendingFeedback table
        /// </summary>
        public static int PendingFeedback_ExpireDays;

        /// <summary>
        /// Specifies after how many days from trip departure date the pending feedbacks are visible and can be left
        /// </summary>
        public static int displayPendingFeedbackAfterDays;

        /// <summary>
        /// Specifies the max number of trips to return with pending feedbacks
        /// </summary>
        public static int MaxNumberOfUserTripsWithPendingFeedbacksToReturn;

        #endregion
        
        #region PendingFeedbacks & insert released feedback region

        /// <summary>
        /// This method is called when a passenger is accepted on a trip and inserts the pending feedbacks in the db.
        /// </summary>
        /// <param name="tripID">The trip ID which the passenger has joined</param>
        /// <param name="psnID">The passenger ID</param>
        /// <param name="vehicleIsCar">A boolean which specifies if the trip vehicle is a car</param>
        /// <returns>A boolean that indicates the operation status</returns>
        public static bool insertPendingFeedbacksOnPSNTripJoin(int tripID, int psnID, bool vehicleIsCar)
        {
            //PendingFeedbacksCache.insertPendingFeedbacksOnPSNTripJoin(tripID,psnID,vehicleIsCar);
            return AuxUserMethods.insertPendingFeedbacksOnJoinOperation(tripID, psnID, vehicleIsCar);
        }
        
        /// <summary>
        /// This method deletes the pending feedbacks that should be left from the specified user for the specified trip.
        /// This method can be invoked when a trip owner cancels the trip few moments before the trip departure date..
        /// so the owner cannot leave any feedback to the joined passengers but they can send a negative feedback to him if wants.
        /// This method can be invoked when a passenger who reserve one or more seats cancels his reservation few moments before the trip departure date..
        /// so the passenger cannot leave any feedback to the owner who can send a negative feedback to him if wants.
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <param name="tripID">The trip ID</param>
        /// <returns></returns>
        public static bool deletePendingFeedbacksFromThisUserForTrip(int userID, int tripID)
        {
            return AuxUserMethods.deletePendingFeedbacksFromThisUserForTripOperation(userID, tripID);
        }
                
        /// <summary>
        /// This methods returns how many pending feedbacks a user has to left.
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <returns>The number of pending feedbacks the user had to left</returns>
        public static int hasPendingFeedbacks(int userID)
        {
            return AuxUserMethods.hasPendingFeedbacksOperation(userID);
        }

        /// <summary>
        /// This methods returns a list of trips which the user has a pending feedback to left
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <returns>A list of trips which the user has a pending feedback to left</returns>
        public static List<TripProperties> getUserTripsWithPendingFeedbacks(int userID)
        {
            return AuxUserMethods.getUserTripsWithPendingFeedbacksOperation(userID);
        }

        /// <summary>
        /// This method returns a list of pending feedbacks associated with the specified trip
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <param name="tripID">The trip ID</param>
        /// <returns>A list of pending feedbacks associated with the specified trip</returns>
        public static List<FeedbackRequest> getPendingFeedbacksForTrip(int userID, int tripID)
        {
            return AuxUserMethods.getPendingFeedbacksToLeaveForTripOperation(userID, tripID);
        }

        /// <summary>
        /// This method is called when a feedback is left and manages this released feedback updating db tables with the new feedback
        /// </summary>
        /// <param name="releasedFeedback">A releasedFeedback object</param>
        /// <returns>A boolean that indicates the operation status</returns>
        public static bool insertReleasedFeedback(ReleasedFeedback releasedFeedback)
        {
            return UpdateFeedbackModule.manageReleasedFeedback(releasedFeedback);
        }
        
        /// <summary>
        /// This method cleans the pending feedbacks table in db removing the expired pending feedbacks...
        /// A pending feedback expires when are passed displayPendingFeedbackAfterDays+PendingFeedback_ExpireDays days from the related trip departure date.
        /// </summary>
        public static void cleanExpiredPendingFeedbacks()
        {
            AuxMethods.cleanExpiredPendingFeedbacksOperation();
        }

        #endregion
        
        #region get user feedbacks region

        /// <summary>
        /// This method is called by groupware and contains operations to retrieve user driver feedback and returns 
        /// an AsDriverFeedback object
        /// </summary>
        /// <param name="userID">UserID to view the feedback as driver</param>
        /// <returns>AsDriverFeedback object</returns>
        public static AsDriverFeedback getAsDriverFeedback(int userID)
        {
            return GetFeedbackModule.getAsDriverFeedbackOperation(userID);
        }
        
        /// <summary>
        /// This method is called by groupware and contains operations to retrieve user passenger feedback and returns 
        /// an AsPassengerFeedback object
        /// </summary>
        /// <param name="userID">userID to view the feedback as passenger</param>
        /// <returns>AsPAssengerFeedback object</returns>
        public static AsPassengerFeedback getAsPassengerFeedback(int userID)
        {
            return GetFeedbackModule.getAsPassengerFeedbackOperation(userID);
        }
        
        /// <summary>
        /// This method is called by groupware and contains operations to retrieve user general feedback and returns 
        /// an GeneralFeedback object
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <returns>A GeneralFeedback object</returns>
        public static GeneralFeedback getGeneralFeedback(int userID)
        {
            return GetFeedbackModule.getGeneralFeedbackOperation(userID);
        }
        
        /// <summary>
        /// This method is called by anonymizer and contains operations to retrieve TriploA feedback list for the user specified..returns 
        /// a Feedback [] vector
        /// </summary>
        /// <param name="userID">UserID</param>
        /// <returns>a vector of Feedback objects</returns>
        public static List<Feedback> getUserFeedbackList(int userID)
        {
            return GetFeedbackModule.getUserFeedbackListOperation(userID);
        }
                
        #endregion

        #region user profile region

        /// <summary>
        /// This method is called by groupware and contains operations to retrieve the user profile and returns 
        /// an UserProfile object
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <returns>A UserProfile object</returns>
        public static UserProfile getUserProfile(int userID)
        {
            return UserProfileModule.getUserProfileOperation(userID);

        }

        #endregion

        #region user - vehicle region

        /// <summary>
        /// This method is called to set the user generic vehicle type from generic cars and motorbike and inserts the associated emissions
        /// and fuel consumption values in the user entry in db.
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <param name="vehicleType">The vehicle type selected by the user</param>
        /// <returns>A boolean that indicates the operation status</returns>
        public static bool setUserVehicleType(int userID, int vehicleType)
        {
            return AuxUserMethods.setVehicleTypeOperation(userID, vehicleType);
        }
        
        /// <summary>
        /// This method is called to get the user selected vehicle type from db
        /// </summary>
        /// <param name="userID">The user ID</param>
        /// <returns>The vehicle type set by the user (Vehicle Types are defined in this class)</returns>
        public static int getUserVehicleType(int userID)
        {
            return AuxUserMethods.getVehicleTypeOperation(userID);
        }

        #endregion
        
        #region daily stats region

        /// <summary>
        /// This method  contains operations to retrieve TriploA general statistics and returns 
        /// a GeneralStats object
        /// </summary>
        /// <returns>A GeneralStats object</returns>
        public static GeneralStats getGeneralStats()
        {
            return GeneralStatsModule.getGeneralStatsOperation();
        }

        /// <summary>
        /// This method updates the daily statistics table inserting the calculated values for yesterday.
        /// </summary>
        public static void updateDailyStats()
        {
            UpdateDailyStatsTableModule.updateDailyStatsTable(DateTime.Today.AddDays(-1),false,false);
        }
               
        /// <summary>
        /// This method starts the daemon which updates the daily statistics table calling the updateDailyStats method every tot hours 
        /// </summary>
        public static void startStatsDaemon()
        {
            updateDailyStats();
            System.Timers.Timer t = new System.Timers.Timer();
            t.Elapsed +=new System.Timers.ElapsedEventHandler(timer_Elapsed);
            t.Interval = 21600000; /* the daemon starts every 6 hours (could be a larger interval) */
            t.Start();
        }

        static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            updateDailyStats();
        }
        
        #endregion

        #region methods to retrieve last N registered users & last 10 created trips & total emissions saved

        /// <summary>
        /// This method returns the last n TripLOA registered users infos
        /// </summary>
        /// <param name="n">The number of TripLOA registered user to return</param>
        /// <returns>A list with the last n TripLOA registered users infos</returns>
        public static List<RegisteredUser> getLastNRegisteredUsers(int n)
        {
            return AuxMethods.getLastNRegisteredUsersOperation(n);
        }

        /// <summary>
        /// This method returns the last N created trips infos
        /// </summary>
        /// <param name="n">The number of TripLOA created trips to return</param>
        /// <returns>A list which contains the last n created trips infos</returns>
        public static List<TripProperties> getLastNCreatedTrips(int n)
        {
            return AuxMethods.getLastNCreatedTripsOperation(n);
        }

        /// <summary>
        /// This method returns the number of non-banned registered users
        /// </summary>
        /// <returns>The number of non-banned registered users</returns>
        public static int getRegisteredUsersCount()
        {
            return AuxMethods.getRegisteredUsersCountOperation();
        }

        /// <summary>
        /// This method returns the number of non-draft created trips
        /// </summary>
        /// <returns>The number of non-draft created trips</returns>
        public static int getCreatedTripsCount()
        {
            return AuxMethods.getCreatedTripsCountOperation();
        }

        /// <summary>
        /// calculates how many health dangerous emissions have been avoided since the moment of the invocation using TripLOA.
        /// </summary>
        /// <returns>the quantity of saved emissions in quintals of CO2</returns>
        public static double getTotalEmissionsSaved()
        {
            return AuxMethods.getTotalEmissionsSaved();
        }

        #endregion
    }
}


